package 栈与队列;

import java.util.Stack;

/**
 * 71. 简化路径
 *
 * 给你一个字符串 path ，表示指向某一文件或目录的 Unix 风格 绝对路径 （以 '/' 开头），请你将其转化为 更加简洁的规范路径。
 *
 * 在 Unix 风格的文件系统中规则如下：
 * 一个点 '.' 表示当前目录本身。
 * 此外，两个点 '..' 表示将目录切换到上一级（指向父目录）。
 * 任意多个连续的斜杠（即，'//' 或 '///'）都被视为单个斜杠 '/'。
 * 任何其他格式的点（例如，'...' 或 '....'）均被视为有效的文件/目录名称。
 * 返回的 简化路径 必须遵循下述格式：
 * 始终以斜杠 '/' 开头。
 * 两个目录名之间必须只有一个斜杠 '/' 。
 * 最后一个目录名（如果存在）不能 以 '/' 结尾。
 * 此外，路径仅包含从根目录到目标文件或目录的路径上的目录（即，不含 '.' 或 '..'）。
 * 返回简化后得到的 规范路径 。
 *  思路：
 *     1：分割路径：将路径按照 / 分割为数组 （因为多个连续的/ 也会被视为单个/）
 *     2: 处理路径部分：
 *      - 如果遇到 ，表示当前目录，直接忽略。
 *      - 如果遇到 .，表示上级目录，需要将栈顶的目录弹出（如果有）。
 *      - 如果是其他目录名，将其压入栈中。
 *     3：构建简化路径，将栈中的目录名用 / 连接起来，并在最前面加上 /。
 */
public class L_71 {
    public String simplifyPath(String path) {
        // 使用栈来存储路径中的各个部分
        Stack<String> stack = new Stack<>();
        // 将路径按照 / 分割为数组
        String[] split = path.split("/");
        // 遍历分割后的路径部分
        for (String s : split){
            // 如果遇到 .. ,表示上级目录，需要将栈顶的目录弹出（如果有）
            if (s.equals("..")){
                if (!stack.isEmpty()){
                    stack.pop();
                }
            }
            // 如果是有效的目录名，则压入栈中 （除了 . 和 .. 外均视为有效的目录名）
            else if (!s.isEmpty() && !s.equals(".")){
                stack.push(s);
            }
        }
        // 构建简化后的路径
        StringBuilder sb = new StringBuilder();
        for (String dir : stack){
            sb.append(dir).append("/");
        }
        // 如果路径不为空，去掉最后一个多余的 /
        if (!sb.isEmpty()){
            sb.deleteCharAt(sb.length() - 1);
        }
        // 返回简化后的路径，并在最前面加上 /
        return "/" + sb.toString();
    }
}
